package utility;

import it.uniroma2.Executor;
import it.uniroma2.ExponentialDistribution;

import it.uniroma2.MonitorClient;
import it.uniroma2.cloud.PROVIDER;
import it.uniroma2.monitor.client.DateUtils;
import it.uniroma2.monitor.client.MetricRequest;
import it.uniroma2.monitor.client.MetricResult;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Random;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.uncommons.maths.random.ExponentialGenerator;
import org.uncommons.maths.random.MersenneTwisterRNG;

public class ServiceRateTester {

	private static int minutesPerClass = 15;
	private static int warmUp = 5;

	/**
	 * @param args
	 * @throws InterruptedException
	 * @throws IOException
	 */

	public static void main(String[] param) throws InterruptedException,
			IOException {

		PrintWriter resultOut = new PrintWriter(new FileOutputStream(new File(
				System.getenv("HOME") + File.separator + "result_"
						+ new Date().toString()), true));

		MonitorClient monitorClient = MonitorClient.getInstance();
		// PROVIDER provider = PROVIDER.AWS_EC2;

		ArrayList<String> classes = new ArrayList<String>();
		classes.add("size_0_100");
		classes.add("size_101_200");
		classes.add("size_201_300");
		classes.add("size_301_400");

		ArrayList<Double> rates = new ArrayList<Double>();
		rates.add(3D);
		rates.add(6D);
		rates.add(9D);
		rates.add(12D);
		rates.add(15D);
		rates.add(18D);
		rates.add(21D);

		for (Double rate : rates) {
			for (String _class : classes) {
				resultOut.println("\n===Starting " + _class + " with rate "
						+ rate);

				DateTime start = new DateTime(DateTimeZone.UTC);
				resultOut.println(start);
				resultOut.flush();
				ExponentialDistribution fixedRate = new ExponentialDistribution(
						rate,
						// new Executor(
						// System.getenv("HOME") + File.separator
						// + "workload/output/" + _class,
						// "http://160.80.85.76/imagetranscoder/imageServlet",
						// false), minutesPerClass);

						new Executor(
								System.getenv("HOME") + File.separator
										+ "workload/output/" + _class,
								"http://160.80.85.76:8080/controller/loadbalancer",
								true), minutesPerClass);

				DateTime end = new DateTime(DateTimeZone.UTC);
				resultOut.println("\n===End @" + end);
				resultOut.flush();
				for (PROVIDER provider : PROVIDER.values()) {
					// Monitor
					DateTime from = DateUtils.lastMinutes(end, minutesPerClass
							- warmUp);
					MetricRequest reqClientDuration = new MetricRequest(
							"*.client.duration.mean", from, end);
					MetricResult resultClientDuration = monitorClient
							.makeRequest(reqClientDuration);
					resultOut.println("\nClientDuration mean - " + _class
							+ " with rate " + rate + ": "
							+ resultClientDuration.avg());

					MetricRequest reqProcessing = new MetricRequest(
							"post.aggregated."
									+ provider.name()
									+ ".imagetranscoder.processing-duration.mean",
							from, end);
					MetricResult resultProcessing = monitorClient
							.makeRequest(reqProcessing);
					resultOut.println("\nProcessingDuration on " + provider
							+ " - " + _class + " with rate " + rate + " : "
							+ resultProcessing.avg());

					resultOut.println("\nLatency on "
							+ provider
							+ ": "
							+ (resultClientDuration.avg() - resultProcessing
									.avg()) + " ms");
					resultOut.flush();

					// Load
					MetricRequest req = new MetricRequest("post.aggregated."
							+ provider.name()
							+ ".imagetranscoder.monitor.load.loadAverage-1Min",
							from, end);
					MetricResult result = monitorClient.makeRequest(req);
					resultOut.println("LoadCheck on " + provider + ": "
							+ result.avg());
					resultOut.flush();

					// CPU
					MetricRequest reqCPU = new MetricRequest(
							"post.aggregated."
									+ provider.name()
									+ ".imagetranscoder.monitor.cpu.cpu-process-percent",
							from, end);
					MetricResult resultCPU = monitorClient.makeRequest(reqCPU);
					resultOut.println("CPU on " + provider + ": "
							+ resultCPU.avg());
					resultOut.flush();

					// Instances
					MetricRequest reqHowMany = new MetricRequest(
							"master.controller." + provider.name()
									+ ".howManyInstances", from, end);
					MetricResult resultHowMany = monitorClient
							.makeRequest(reqHowMany);
					resultOut.println("How many instances on " + provider
							+ ": " + resultHowMany.avg());
					resultOut.flush();

					// Service rate
					MetricRequest reqServiceRate = new MetricRequest(
							"post.aggregated." + provider.name()
									+ ".imagetranscoder.serviceRate.m1_rate",
							from, end);
					MetricResult resultServiceRate = monitorClient
							.makeRequest(reqServiceRate);
					resultOut.println("ServiceRate on " + provider + ": "
							+ resultServiceRate.avg());
					resultOut.flush();
				}
			}
		}
		resultOut.close();
	}

}
